package com.itheima.sh.esdemo;

import com.alibaba.fastjson.JSON;
import com.itheima.sh.esdemo.pojo.User;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpHost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.Fuzziness;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import java.io.IOException;

/**

 */
public class ESSearch1 {

    private RestHighLevelClient client;

    @Before
    public void init() {
        //创建Rest客户端
        client = new RestHighLevelClient(
                RestClient.builder(
                        //如果是集群，则设置多个主机，注意端口是http协议的端口
                        new HttpHost("192.168.200.150", 9200, "http")
                )
        );
    }


    public void printResultByQuery(QueryBuilder queryBuilder) throws IOException {
        //创建SearchSourceBuilder对象
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //添加查询条件QueryBuilders.termQuery()
        sourceBuilder.query(queryBuilder);
        //------------添加排序
        sourceBuilder.sort("id", SortOrder.DESC);

        //------------添加分页
        int page = 1; //当前页
        int size = 3; //一页显示数量
        int from = (page - 1) * size;  //每一页起始条数
        sourceBuilder.from(from);
        sourceBuilder.size(size);

        //-------------设置高亮
        HighlightBuilder highlight = SearchSourceBuilder.highlight();
        highlight.field("note");
        highlight.preTags("<font color = 'red'>");
        highlight.postTags("</font>");
        sourceBuilder.highlighter(highlight);
        //创建SearchRequest对象，并制定索引库名称
        SearchRequest request = new SearchRequest("user");
        //添加SearchSourceBuilder对象到SearchRequest对象source中
        request.source(sourceBuilder);
        //发起请求，得到结果
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //解析结果SearchResponse
        SearchHits hits = response.getHits();
        //获取总条数
        System.out.println("总条数:" + hits.getTotalHits().value);
        //获取SearchHits数组，并遍历
        for (SearchHit hit : hits) {
            //获取其中的_source，是JSON数据
            String json = hit.getSourceAsString();
            //把_source反序列化为User对象
            User user = JSON.parseObject(json, User.class);

            //-----------解析高亮数据
            HighlightField highlightField = hit.getHighlightFields().get("note");
            Text[] fragments = highlightField.getFragments();  //变为数组
            String note = StringUtils.join(fragments);
            //判断如果是可以获取的数据则更新到用户对象中
            if (StringUtils.isNotBlank(note)) {
                user.setNote(note);
            }
            System.out.println("user = " + user);
        }

    }

    @After
    public void close() {
        try {
            if (client != null) {
                client.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }



    //match :分词匹配查询 ,默认取并集,or note中有"小红"或者"同学"的都将查询出来

    /*GET /user/_search
    {
        "query": {
        "match": {
            "note": "小红同学"
        }
    }
    }*/
    @Test
    public void matchSearch() throws IOException {
        MatchQueryBuilder queryBuilder = QueryBuilders.matchQuery("note", "小红同学");
        printResultByQuery(queryBuilder);
    }


    //fuzzy: 模糊查询  默认会按照一定的规则来修正当前查询的条件，修正的次数最大是 2次，可取值为：0、1、2，大于2则按照最大值计算。

    /*GET /user/_search
    {
        "query": {
        "fuzzy": {
            "note": {
                "value": "黑程序马员",
                        "fuzziness": 2
            }
        }
    }
    }*/
    @Test
    public void fuzzySearch() throws IOException {
        FuzzyQueryBuilder queryBuilder = QueryBuilders.fuzzyQuery("note", "黑程马序员");
        queryBuilder.fuzziness(Fuzziness.TWO);
        printResultByQuery(queryBuilder);
        System.out.println(queryBuilder.value());
    }


    //range:范围查询&排序
    /*GET /user/_search
    {
        "query": {
        "range": {
            "age": {
                "gte": 20,
                        "lte": 25
            }
        }
    },
        "sort": [
        {
            "id": {
            "order": "desc"
        }
        }
  ]
    }*/
    @Test
    public void rangeAndSort() throws IOException {
        RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("age");
        queryBuilder.gte(20);
        queryBuilder.lt(25);
        printResultByQuery(queryBuilder);
    }


    //queryString :多条件查询
    /*GET /user/_search
    {
        "query": {
        "query_string": {
      #"fields": ["name","note"],   //和最后一行不能同时存在
            "query": "黑马同学",
                    "default_operator": "AND",
                    "default_field": "note"   //默认搜索区
        }
    }
    }*/
    @Test
    public void queryString() throws IOException {
        QueryStringQueryBuilder queryBuilder = QueryBuilders.queryStringQuery("黑马同学")
                .field("name")
                .field("note")
//                .defaultField("note")
                .defaultOperator(Operator.AND);
        printResultByQuery(queryBuilder);
    }


    //bool :对多个查询条件连接 连接方式：
            //must（and）：条件必须成立
            //must_not（not）：条件必须不成立
            //should（or）：条件可以成立
            //filter：条件必须成立，性能比must高。不会计算得分
    /*GET /user/_search
    {
        "query": {
        "bool": {
            "should": [
            {
                "match": {
                "note": "黑马"
            }
            }
      ],
            "filter": [
            {
                "match":{
                "name":"小明"
            }
            },
            {
                "range":{
                "age":{
                    "gte":19,
                            "lt":25
                }
            }
            }
      ]
        }
    }
    }*/
    @Test
    public void boolSearch() throws IOException {
        //构建bool条件对象
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        //构建matchQuery对象 放入bool的must连接方式
        MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("note", "黑马");
        queryBuilder.must(matchQueryBuilder);

        //过滤
        TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery("name", "小明");
        queryBuilder.filter(termQueryBuilder);

        //再次过滤
        RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");
        rangeQueryBuilder
                .gte(15)
                .lt(30);
        queryBuilder.filter(rangeQueryBuilder);
        printResultByQuery(queryBuilder);
    }


//分页查询
    /*GET /user/_search
    {
        "query": {
        "bool": {
            "must": [
            {
                "match": {
                "note": "同学黑马"
            }
            }
      ]
        }
    },
        "sort": [
        {
            "id": {
            "order": "desc"
        }
        }
  ],
        "from": 0,     #开始记录数from = (page-1)*size
            "size": 3
    }*/
    @Test
    public void pageSearch() throws IOException {
        BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery();
        MatchQueryBuilder matchQuery = QueryBuilders.matchQuery("note", "同学黑马");
        queryBuilder.must(matchQuery);
        printResultByQuery(queryBuilder);
    }


    //highlight :高亮
    /*GET /user/_search
    {
        "query": {
        "bool": {
            "must": [
            {
                "match": {
                "note": "黑马"
            }
            }
      ]
        }
    },
        "highlight": {
        "fields": {
            "note": {
                "pre_tags": "<font color = 'red'>",
                        "post_tags": "</font>"
            }
        }
    }
    }
*/

    @Test
    public void hightlightSearch(){

    }
}
